"""
浏览器自动化工具类
提供基础的浏览器操作功能
"""
import time
import json
import logging
from typing import Optional, List, Any
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import TimeoutException, NoSuchElementException, WebDriverException


class BrowserDriver:
    """浏览器驱动封装类"""
    
    def __init__(self, config: dict):
        self.config = config
        self.driver: Optional[webdriver.Chrome] = None
        self.wait: Optional[WebDriverWait] = None
        self.logger = self._setup_logger()
    
    def _setup_logger(self) -> logging.Logger:
        """设置日志记录器"""
        logger = logging.getLogger('BrowserDriver')
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger
    
    def init_driver(self) -> None:
        """初始化浏览器驱动，优先使用项目根目录 chromedriver.exe"""
        try:
            chrome_options = Options()
            # 基础配置
            if self.config['browser']['headless']:
                chrome_options.add_argument('--headless')
            chrome_options.add_argument(f'--window-size={self.config["browser"]["window_size"]}')
            chrome_options.add_argument(f'--user-agent={self.config["browser"]["user_agent"]}')
            # 优化配置
            chrome_options.add_argument('--no-sandbox')
            chrome_options.add_argument('--disable-dev-shm-usage')
            chrome_options.add_argument('--disable-gpu')
            chrome_options.add_argument('--disable-blink-features=AutomationControlled')
            chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])
            chrome_options.add_experimental_option('useAutomationExtension', False)
            # 禁用图片加载以提高速度
            prefs = {
                'profile.managed_default_content_settings.images': 2,
                'profile.default_content_setting_values.notifications': 2
            }
            chrome_options.add_experimental_option('prefs', prefs)


            import os
            from selenium.webdriver.chrome.service import Service
            chromedriver_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'chromedriver.exe')
            if os.path.exists(chromedriver_path):
                service = Service(chromedriver_path)
                self.driver = webdriver.Chrome(service=service, options=chrome_options)
            else:
                # 如果根目录没有 chromedriver.exe，则尝试系统 PATH
                self.driver = webdriver.Chrome(options=chrome_options)

            self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
            # 设置超时时间
            self.driver.implicitly_wait(self.config['browser']['implicit_wait'])
            self.driver.set_page_load_timeout(self.config['browser']['page_load_timeout'])
            self.wait = WebDriverWait(self.driver, 10)
            self.logger.info("浏览器驱动初始化成功")
        except Exception as e:
            self.logger.error(f"浏览器驱动初始化失败: {e}")
            raise
    
    def get_page(self, url: str) -> None:
        """访问指定页面"""
        try:
            self.logger.info(f"正在访问: {url}")
            self.driver.get(url)
            time.sleep(2)  # 等待页面加载
        except Exception as e:
            self.logger.error(f"访问页面失败: {e}")
            raise
    
    def find_element(self, by: By, value: str, timeout: int = 10) -> Any:
        """查找单个元素"""
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((by, value))
            )
            return element
        except TimeoutException:
            self.logger.warning(f"元素未找到: {by}={value}")
            return None
        except Exception as e:
            self.logger.error(f"查找元素出错: {e}")
            return None
    
    def find_elements(self, by: By, value: str, timeout: int = 10) -> List[Any]:
        """查找多个元素"""
        try:
            WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((by, value))
            )
            return self.driver.find_elements(by, value)
        except TimeoutException:
            self.logger.warning(f"元素未找到: {by}={value}")
            return []
        except Exception as e:
            self.logger.error(f"查找元素出错: {e}")
            return []
    
    def click_element(self, by: By, value: str, timeout: int = 10) -> bool:
        """点击元素"""
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.element_to_be_clickable((by, value))
            )
            element.click()
            time.sleep(0.5)
            return True
        except TimeoutException:
            self.logger.warning(f"元素不可点击: {by}={value}")
            return False
        except Exception as e:
            self.logger.error(f"点击元素出错: {e}")
            return False
    
    def input_text(self, by: By, value: str, text: str, clear: bool = True, timeout: int = 10) -> bool:
        """输入文本"""
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((by, value))
            )
            if clear:
                element.clear()
            element.send_keys(text)
            time.sleep(0.3)
            return True
        except TimeoutException:
            self.logger.warning(f"输入框未找到: {by}={value}")
            return False
        except Exception as e:
            self.logger.error(f"输入文本出错: {e}")
            return False
    
    def wait_for_element_visible(self, by: By, value: str, timeout: int = 10) -> bool:
        """等待元素可见"""
        try:
            WebDriverWait(self.driver, timeout).until(
                EC.visibility_of_element_located((by, value))
            )
            return True
        except TimeoutException:
            return False
        except Exception as e:
            self.logger.error(f"等待元素可见出错: {e}")
            return False
    
    def execute_script(self, script: str) -> Any:
        """执行JavaScript"""
        try:
            return self.driver.execute_script(script)
        except Exception as e:
            self.logger.error(f"执行脚本出错: {e}")
            return None
    
    def switch_to_window(self, window_index: int = -1) -> None:
        """切换到指定窗口"""
        try:
            windows = self.driver.window_handles
            if window_index == -1:
                window_index = len(windows) - 1
            self.driver.switch_to.window(windows[window_index])
        except Exception as e:
            self.logger.error(f"切换窗口出错: {e}")
    
    def get_current_url(self) -> str:
        """获取当前URL"""
        try:
            return self.driver.current_url
        except Exception as e:
            self.logger.error(f"获取当前URL出错: {e}")
            return ""
    
    def refresh_page(self) -> None:
        """刷新页面"""
        try:
            self.driver.refresh()
            time.sleep(2)
        except Exception as e:
            self.logger.error(f"刷新页面出错: {e}")
    
    def close_driver(self) -> None:
        """关闭浏览器驱动"""
        try:
            if self.driver:
                self.driver.quit()
                self.logger.info("浏览器驱动已关闭")
        except Exception as e:
            self.logger.error(f"关闭浏览器驱动出错: {e}")
    
    def take_screenshot(self, filename: str) -> None:
        """截图"""
        try:
            self.driver.save_screenshot(filename)
            self.logger.info(f"截图已保存: {filename}")
        except Exception as e:
            self.logger.error(f"截图失败: {e}")